#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

__Author__ = "Haelwenn Monnier (lanodan) <haelwenn.monnier@gmail.com>"
__License__ = "CC-BY-SA"

import socket, sys, re, time, urllib

tetris=0
urlRegex = re.compile('(https?|ftp)://', flags=re.IGNORECASE)

# Load config
try:
	import conf
except Exception as e:
	print('Exception: {}'.format(str(e)))
	print('Exiting…')
	sys.exit(1)

def get_element(dataInput, elem):
	idx1=dataInput.find('<{}>'.format(elem))
	idx2=dataInput.find('</{}>'.format(elem))
	return dataInput[idx1+len('<{}>'.format(elem)):idx2].strip()

# Output to the channel and console
def privmsg(msg, destination = conf.channel):
	irc.send('PRIVMSG {}: {}\r\n'.format(destination, msg))
	print('PRIVMSG {}: {}'.format(destination, msg))

#line: append to the log (output it to the console too)
def log(line):
	print('[LOG]'+line)
	log = open('IRCBot.log', 'a')
	log.write('{}\n'.format(line))
	log.close()

def sendCommand(command, docrlf=True):
	if docrlf:
		irc.send('{command}\r\n'.format_map())
		print('{}\r\n'.format(command))
	else:
		irc.send(command)
		print(command)

# === Main script ===
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

irc.connect((conf.server, conf.port))
#if SSLEnabled:
#	irc = ssl.wrap_socket(irc)
#
if conf.passwd is not None:
	sendCommand('PASS {}'.format(conf.passwd))

if conf.nick is not None:
	sendCommand('NICK {}'.format(conf.nick))
	sendCommand('USER {} irc bot :Bot made by lanodan using python3!'.format(conf.nick))
else:
	print('You must define a nick, see conf.py.example')
	sys.exit(1)

#while 1:
#	if irc.recv(2048).find('372') != -1:
if conf.channel is not None:
	sendCommand('JOIN {}'.format(conf.channel))
#		break

time.sleep(1.5) # Random wait time, feel free to adjust it
#while 1:
#	if irc.recv(2048).find('JOIN '+channel) != -1:
if conf.welcomeMsg is not None:
	privmsg(conf.welcomeMsg)
#		break

# Make a while loop to alway parse input
while 1:
	data = irc.recv(2048) # text is the socket input (I use text because input is already taken)
	text = data.lower() # text is the socket input (I use text because input is already taken)
	print(data) # print the input for debugging purpose

	data_splitted = data[1:].split(' ', 3)

	if data[0] == ':':
		data_usermask = data_splitted[0]
		data_username = data_usermask.split('!')[0]
		data_command  = data_splitted[1]
		data_origin  = data_splitted[2]
		data_msg      = ''.join(data_splitted[3][1:]).strip()
		print('[DEBUG] data_msg =', data_msg)

		if conf.separator in data_msg[0]: # "in" allows to put multiple separators
			command_arg = data_msg[1:].split(' ')
			print('[DEBUG] command_arg =', command_arg)

			if 'hi' == command_arg[0]:
				try:
					print(len(command_arg[1]))
					type(command_arg[1])
					if len(command_arg[1]) is not None:
						name = ''.join(command_arg[1:])
				except IndexError:
					name = data_username
				print('[DEBUG] name =', name)
				privmsg('{}: {}'.format(''.join(command_arg[1:]), conf.welcomeMsg), destination = data_origin)
			elif 'say' == command_arg[0]:
				privmsg(''.join(command_arg[1:]), destination = data_origin)
			elif 'action' == command_arg[0]:
				privmsg('\x01ACTION {} \x01'.format(''.join(command_arg[1:])), destination = data_origin)
			elif 'source' == command_arg[0]:
				privmsg(conf.source, destination = data_origin)
			elif 'tetris' in data_msg:
				privmsg('Never gonna give you up.')
				privmsg('Never gonna let you down.')
				privmsg('Never gonna run around and desert you.')
				privmsg('Never gonna make you cry.')
				privmsg('Never gonna say goodbye.')
				privmsg('Never gonna tell a lie and hurt you.')
				tetris=1 # Prevent another rick roll
			elif 'nsidentify' == command_arg[0]:
				sendCommand('NS identify {}'.format(conf.passwd))
			elif 'msgidentify' == command_arg[0]:
				privmsg('identify {}'.format(conf.passwd), destination = conf.NickServ)
			elif urlRegex.search(data_msg) is not None: # Use httpRegex on input
				url = re.findall('(?:https?|ftp)://[\w\$-_.+!*\'(),;\/\?\:\@\=\&]+', data, flags=re.IGNORECASE)[0] # parse URL
				print('Url:', url)
				try:
					if (len(url) > 8): # I assume a link is more than 8 characters long
						try:
							get = urllib.request.urlopen(url) # Open the link
							wget = get.read() # Read the input of the url
							print(get.info()) # Print Headers
							mimeType = get.info().type # Get the Content-Type
							get.close() # Close the connection
							# find the title
							if wget.find('<title>') != -1:
								title = get_element(wget, 'title')
								privmsg('Title: '+title)
								log('{}; {}; {}'.format(url, str(mimeType), title))
							elif wget.find('<TITLE>') != -1:
								title = get_element(wget, 'TITLE')
								privmsg('Title: '+title)
								log('{}; {}; {}'.format(url, str(mimeType), title))
							#If we can't find the title print the Content-Type
							else:
								privmsg('Content-Type: '+mimeType)
								log('{}; {}'.format(url, str(mimeType)))
						except Exception as e:
							privmsg('Exception: {}'.format(str(e)))
					else:
						privmsg('Link too short (not more than 8)')
				except Exception as e:
					privmsg('Exception: {}'.format(str(e)))
			elif 'JOIN' == data_command:
				if ('fuyuneko', 'lanodan') in data_username:
					privmsg('{}: Okaeri-nasai hime-sama'.format(data_username))
				else:
					privmsg('{}: '.format(data_username, conf.welcomeMsg))
			elif 'KICK' == data_command and conf.nick == data_username:
				time.sleep(5)
				sendCommand('JOIN '+conf.channel) #re-join the chan
				privmsg(welcomeMsg) # Say hello
			elif 'stop in the name of sey' == ''.join(command_arg[0:]):
				sendCommand('QUIT :{}'.format(conf.quitMsg))
				time.sleep(1)
				break
	else:
		if data_splitted[0] == 'PING':
			sendCommand('PONG {} {}'.format(conf.nick, ''.join(data.split(': '))))
		elif data is None:
			sendCommand('QUIT :Empty socket input')
			time.sleep(1)
			break

irc.close()
sys.exit()
